(in-package :TRAPS)
; Generated from #P"macintosh-hd:hd3:CInterface Translator:Source Interfaces:PPCI2CInterface.h"
; at Sunday July 2,2006 7:31:17 pm.
; 
;  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
;  *
;  * @APPLE_LICENSE_HEADER_START@
;  * 
;  * The contents of this file constitute Original Code as defined in and
;  * are subject to the Apple Public Source License Version 1.1 (the
;  * "License").  You may not use this file except in compliance with the
;  * License.  Please obtain a copy of the License at
;  * http://www.apple.com/publicsource and read it before using this file.
;  * 
;  * This Original Code and all software distributed under the License are
;  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
;  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
;  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
;  * License for the specific language governing rights and limitations
;  * under the License.
;  * 
;  * @APPLE_LICENSE_HEADER_END@
;  
; 
;  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
;  *
;  * Interface definition for the keylargo I2C interface
;  *
;  * HISTORY
;  *
;  
; #ifndef _PPCI2CINTERFACE_H
; #define _PPCI2CINTERFACE_H 

(require-interface "IOKit/IOTypes")

(require-interface "IOKit/IOLib")

(require-interface "IOKit/IOLocks")

(require-interface "IOKit/IOSyncer")

(require-interface "IOKit/IOService")
;  IMPORTANT NOTE:
;  This driver provides the basic functionality to communicate with
;  devices on the i2c bus. To "talk" with a device the developer needs
;  first to find the i2c interface. This is very easy since the driver
;  does a registerService. Once the client has a reference to this
;  driver it needs to follow the following important rule:
;  HOLD THE BUS FOR AS SHORT AS POSSIBLE !!! Since each client may need
;  to access to the bus in a different way it is not "polite" to hold the
;  bus for a long time. For example opening the i2c bus in ::start and closing
;  it in ::stop is very bad (and most of all it will not work, to try to
;  enforce corectness in using the driver I make sure that the tread that
;  opens is the same that uses the other functionalities).
;  This is a good way to use the bus:
;  open i2c
;  setup the bus in the way you need to use it
;  do the the write/read (or block of writes and reads)
;  close the 12c.
;  the sequence open/setup/use/close should be as compact as possible
;  (it is great if it is concertrated all in the same function) and
;  it MUST be all in the same thread.
;  class ApplePMUInterface;  //not necessary
; #define busTypeString (i2cPMU ? "i2cPMU" : (i2cUniN ? "i2cUniN" : (i2cmacio ? "i2cmacio" : "i2cUnkn")))
;  Clients get call backs with this type of function:

(def-mactype :AppleI2Cclient (find-mactype ':pointer)); (IOService * client , UInt32 addressInfo , UInt32 length , UInt8 * buffer)
#|
 confused about CLASS PPCI2CInterface #\: public IOService #\{ OSDeclareDefaultStructors #\( PPCI2CInterface #\) private #\:;  These are the possible states the driver can be in:
 typedef enum #\{ ki2cStateIdle = 0 #\, ki2cStateWaitingForIADDR #\, ki2cStateWaitingForIDATA #\, ki2cStateWaitingForISTOP #\, ki2cStateWaitingForISTART #\, #\} PPCI2CState #\;;  Constansts for the mode register:
 typedef enum #\{ kPortMask = 0x0F              ; 
 #\} I2CPort #\; typedef enum #\{ kDumbMode = 0x00 #\,;  
 kStandardMode = 0x01 #\,                       ; 
 kStandardSubMode = 0x02 #\,                    ; 
 kCombinedMode = 0x03 #\,                       ; 
 kModeMask = 0x03 #\,                           ; 
 kSimpleI2CStream = 0 #\,                       ;  PMU i2c modes			
 kSubaddressI2CStream = 1 #\, kCombinedI2CStream = 2 #\} I2CMode #\; typedef enum #\{ k100KhzMode = 0x00 #\,; 
 k50KhzMode = 0x01 #\,                          ; 
 k25KhzMode = 0x02 #\,                          ; 
 kReservedMode = 0x03 #\,                       ; 
 kSpeedMask = 0x03                              ; 
 #\} I2CSpeed #\; enum #\{ I2CPortShift = 4 #\} #\; enum #\{ I2CModeShift = 2 #\} #\; enum #\{ I2CSpeedShift = 0 #\} #\;;  Constants for the Control register
 typedef enum #\{ kClrCNTRL = 0x00 #\,          ;  0 -> Clears all the control bits
 kAakCNTRL = 0x01 #\,                           ;  1 -> AAK sent, 0 -> not AAK sent
 kXAddrCNTRL = 0x02 #\,                         ;  when set -> transmit address phase (not used by manual mode)
 kStopCNTRL = 0x04 #\,                          ;  when set -> transmit stop condition
 kStartCNTRL = 0x08 #\,                         ;  when set -> transmit start condition (manual mode only)
 kCNTRLMask = 0x0F                              ;  Masks all the control bits
 #\} I2CControl #\; enum #\{ I2CControlShift = 0 #\} #\;;  Constants for the STATUS register
 typedef enum #\{ kBusySTATUS = 0x01 #\,        ;  1 -> busy
 kLastAakSTATUS = 0x02 #\,                      ;  value of last AAK bit
 kLastReadWriteSTATUS = 0x04 #\,                ;  value of last R/W bit transmitted
 kIsdaSTATUS = 0x08 #\,                         ;  data line SDA
 kSclSTATUS = 0x10 #\,                          ;  clock line SCL
 kSTATUSMask = 0x1F                             ;  Mask all the status bits
 #\} I2CStatus #\; enum #\{ I2CStatusShift = 0 #\} #\;;  Constants for the ISR register
 typedef enum #\{ kIDataISR = 0x01 #\,          ;  Data Byte Sent or Received Interrupt
 kIAddrISR = 0x02 #\,                           ;  Address Phase Sent Interrupt
 kIStopISR = 0x04 #\,                           ;  Stop Condition Sent Interrupt
 kIStartISR = 0x08 #\,                          ;  Start Condition Sent Interrupt
 kISRMask = 0x0F #\} I2CInterruptStatus #\; enum #\{ I2CInterruptStatusShift = 0 #\} #\;;  Constants for the IER register
 typedef enum #\{ kEDataIER = 0x01 #\,          ;  Enable Data Byte Sent or Received Interrupt
 kEAddrIER = 0x02 #\,                           ;  Enable AAddress Phase Sent Interrupt
 kEStopIER = 0x04 #\,                           ;  Enable Stop Condition Sent Interrupt
 kEStartIER = 0x08 #\,                          ;  Enable Start Condition Sent Interrupt
 kIERMask = 0x0F #\} I2CInterruptEnable #\; enum #\{ I2CInterruptEnableShift = 0 #\} #\;;  Constants for the Address register
 enum I2CAddress #\{ kADDRMask = 0x7F           ; 
 #\} #\; typedef enum #\{ kWriteADDR = 0x00 #\, ; 
 kReadADDR = 0x01 #\,                           ; 
 kRWMask = 0x01                                 ; 
 #\} I2CRWMode #\; enum #\{ I2CAddressShift = 1 #\} #\; enum #\{ I2CRWShift = 0 #\} #\;;  redefine the types so it makes easyer to handle
;  new i2c if they have wider registers.
 typedef UInt8 * I2CRegister #\; typedef UInt32 * I2CLongRegister #\;;  The ioblock where we have the i2c registers:
 IOMemoryMap * i2cRegisterMap #\;               ;  This is the name of the resource exported by this driver:
 char resourceName #\[ 64 #\] #\;               ;  These are the keylargo registers to access to the
;  i2c bus:
 I2CRegister mode #\;                           ;  Configure the transmission mode of the i2c cell and the databit rate.
 I2CRegister control #\;                        ;  Holds the 4 bits used to start the operations on the i2c interface.
 I2CRegister status #\;                         ;  Status bits for the i2 cell and the i2c interface.
 I2CRegister ISR #\;                            ;  Holds the status bits for the interrupt conditions.
 I2CRegister IER #\;                            ;  Eneables the bits that allow the four interrupt status conditions.
 I2CRegister address #\;                        ;  Holds the 7 bits address and the R/W bit.
 I2CRegister subAddr #\;                        ;  the 8bit subaddress..
 I2CRegister data #\;                           ;  the byte to sents or the last byte received
; #pragma options align=mac68k
 struct i2cRegCopyPB #\{ UInt8 mode #\;         ;  local copies for PMU I2C case (see above for comments)
 UInt8 control #\; UInt8 status #\; UInt8 ISR #\; UInt8 IER #\; UInt8 address #\; UInt8 subAddr #\; UInt8 data #\; #\} #\; typedef struct i2cRegCopyPB i2cRegCopyPB #\;; #pragma options align=reset
;  pointer to local data in PMU case
 i2cRegCopyPB * i2cPBptr #\;                    ; #pragma options align=reset
;   PMU99 I2C command equates (command $9A)
 enum #\{ kPMUI2CCmd = 0x9A #\,                 ;         kSimpleI2CStream            = 0,	// placed in I2CMode			
;         kSubaddressI2CStream        = 1,
;         kCombinedI2CStream          = 2,
 kI2CReplyPendingErr = - 4 #\, kI2CTransactionErr = - 3 #\, kI2CBusyErr = - 2 #\, kI2CParameterErr = - 1 #\, kI2CNoErr = 0 #\, kI2CReadData = 1 #\, kI2CDataBufSize = 249 #\} #\;;  I2C bus types for PMU
 typedef enum #\{ kI2CStatusBus = 0 #\,         ;  pseudo bus used for status retrieval
 kSystemClockBus = 1 #\,                        ;  (Clocks and GPIOs live here, currenlty) 
 kPowerSupplyBus = 2 #\,                        ;  (IVAD is here)
 #\} BusType #\; struct PMUI2CPB #\{ UInt8 bus #\; UInt8 xferType #\; UInt8 secondaryBusNum #\; UInt8 address #\; UInt8 subAddr #\; UInt8 combAddr #\; UInt8 dataCount #\; UInt8 data #\[ 249 #\] #\;;  sizeof(PMUI2CPB) = 256
 #\} #\; typedef struct PMUI2CPB PMUI2CPB #\;
; #define MAXIICRETRYCOUNT	20
; #define STATUS_DATAREAD		1
; #define STATUS_OK		0
; #define STATUS_BUSY		0xfe
;  Parameters for PMU i2c transactions
 PMUI2CPB i2c #\; IOByteCount length #\;        ;  Remembers the provider so when we work as interrupt-driven we can enable and disable the
;  interrupts:
 IOService * myProvider #\;                     ;  Remember if we had a PMU, UniN provider or not
 bool i2cPMU #\; bool i2cUniN #\; bool i2cmacio #\;;  Loop timeout in waitForCompletion();  Defaults to 2 sec interrupt mode, defaults
;   to 15 secs on i2cmacio polling (for audio) and to 3 sec i2cUniN polling
 UInt16 waitTime #\;                            ;  Keeps track of the success (or failure) of the last transfer:
 bool transferWasSuccesful #\;                  ;  When the driver is not in polling mode (so it is interrupt driven) the
;  following assures that all the transactions are syncronous.
 volatile semaphore_t mySync #\;                ;  This is a parameter used in memory cells and useless for
;  the mac-io. It's also the bus number in the PMU:
 UInt8 portSelect #\;                           ;  This is the current state for the driver:
 PPCI2CState currentState #\;                   ;  This interface does not need to be attached to an interrrupt. (it is obvoiusly
;  better to be, but it is not NECESSARY). When it is not attached to an interrupt
;  it works in polling mode. The following bool flag sets the default behavior.
 bool pollingMode #\;                           ;  Only one driver a time can use the I2C bus
;  so this lock provides mutual exclusive accesses. To ensure that
;  the the same thread can access the service after the lock has been
;  obrained I am going to use a recursive lock:
 IORecursiveLock * mutexLock #\;                ;  PMU version needs to block other threads as well until port closed
 IOLock * pmuLock #\; protected #\:             ; ************************************************************************************************
;  Client handling methods and functions:
;  --------------------------------------
;  The i2c clients register with the driver to be notified
;  when some events (interrupts) occur. The driver has so
;  to keep a list of all the clients:
 typedef struct I2Cclient #\{ UInt32 addressInfo #\; IOService * client #\; AppleI2Cclient callBackFunction #\; struct I2Cclient * nextClient #\; #\} I2Cclient #\; typedef I2Cclient * I2CclientPtr #\;;  This is the top of the list:
 I2CclientPtr listHead #\;                      ;  This lock protects the access to the clients
;  list:
 IOLock * clientMutexLock #\;                   ;  Adds a client to the list:
 bool addI2Cclient #\( UInt32 addressInfo #\, AppleI2Cclient function #\, IOService * caller #\) #\;;  Removes a client to the list:
 bool removeI2Cclient #\( UInt32 addressInfo #\, IOService * caller #\) #\;;  Removes all clients from the list:
 bool clearI2CclientList #\( #\) #\;            ;  Calls a client in the list with the data from the current interrupt:
 bool calli2cClient #\( UInt8 interruptMask #\, UInt32 length #\, UInt8 * buffer #\) #\;;  If an other driver wishes to be aware of i2c interrupts
;  it has to register with the i2c driver:
;  Note that clients have rules to follow: the most important is
;  that they should NEVER change the content of the buffer status
;  they receive from the i2c driver.
 bool registerForI2cInterrupts #\( UInt32 addressInfo #\, AppleI2Cclient function #\, IOService * caller #\) #\;;  Only register once for Pmu I2C interrupts, since we will call back all interested clients from ourself
 bool registeredForPmuI2C #\;                   ;  This is to de-register from the clients that  wish to be aware of i2c transactions
 bool deRegisterI2cClient #\( UInt32 addressInfo #\, IOService * caller #\) #\;;  This is the interrupt handler for PMU callbacks of I2C interrupts
 static void handlePMUi2cInterrupt #\( IOService * client #\, UInt8 interruptMask #\, UInt32 length #\, UInt8 * buffer #\) #\;; ************************************************************************************************
;  Caches the last mode set (I would not do this, but each access to getMode requires a mask and a shift):
 I2CMode lastMode #\;                           ;  Caches the last speed set
 I2CSpeed lastSpeed #\;                         ;  pointer to the data to be transfered
 UInt8 * dataBuffer #\;                         ;  and the number of bytes still to transfer
 UInt16 nBytes #\;                              ;  the current transfer address:
 UInt8 currentAddress #\;                       ;  the current transfer subAddress:
 UInt8 currentSubaddress #\;                    ;  Direction of the data
 bool isReading #\;                             ;  prints the content of the registers:
 void dumpI2CRegisters #\( #\) #\;              ;  Given the base of the i2c registers inits all the registers.
 void SetI2CBase #\( UInt8 * baseAddress #\, UInt8 steps #\) #\;;  setAddress and Data for PMU transfer
 void setAddressDataForPMU #\( #\) #\;          ;  send a general purpose call to Apple PMU (uses callPlatformFunction)
 static IOReturn ApplePMUSendMiscCommand #\( UInt32 command #\, IOByteCount sendLength #\, UInt8 * sendBuffer #\, IOByteCount * readLength #\, UInt8 * readBuffer #\) #\;;  send a write I2c packet to PMU, includes status check at end
;  static? 
 bool writePmuI2C #\( UInt8 address #\, UInt8 subAddress #\, UInt8 * buffer #\, IOByteCount count #\) #\;;  send a read I2c packet to PMU, includes status check at end
;  static?
 bool readPmuI2C #\( UInt8 address #\, UInt8 subAddress #\, UInt8 * buffer #\, IOByteCount count #\) #\;;  set up interface for PMU transfer if needed
 bool PPCI2CInterface #\: #\: retrieveProperty #\( IOService * provider #\) #\;;  Returns the mask to use with the register:
 UInt8 shiftedMask #\( UInt8 mask #\, UInt8 shift #\) #\;;  Returns the complement of the mask
 UInt8 shiftedCompMask #\( UInt8 mask #\, UInt8 shift #\) #\;;  Generic read and write for register fields:
 UInt8 readRegisterField #\( I2CRegister #\, UInt8 #\, UInt8 #\) #\; void writeRegisterField #\( I2CRegister #\, UInt8 #\, UInt8 #\, UInt8 #\) #\;;  Intermediate methods to access to each field of all the registers:
;  Mode register:
 void setPort #\( UInt8 #\) #\; UInt8 getPort #\( #\) #\; void setMode #\( I2CMode #\) #\; I2CMode getMode #\( #\) #\; void setSpeed #\( I2CSpeed #\) #\; I2CSpeed getSpeed #\( #\) #\;;  Control register
 void setControl #\( I2CControl #\) #\; I2CControl getControl #\( #\) #\;;  Status register
 void setStatus #\( I2CStatus #\) #\; I2CStatus getStatus #\( #\) #\;;  Interrupt status
 void setInterruptStatus #\( I2CInterruptStatus #\) #\; I2CInterruptStatus getInterruptStatus #\( #\) #\;;  Interrupt enable
 void setInterruptEnable #\( I2CInterruptEnable #\) #\; I2CInterruptEnable setInterruptEnable #\( #\) #\;;  Address Register:
 void setAddressRegister #\( UInt8 #\, I2CRWMode #\) #\; void setAddress #\( UInt8 #\) #\; UInt8 getAddress #\( #\) #\; void setReadWrite #\( I2CRWMode #\) #\; I2CRWMode getReadWrite #\( #\) #\;;  SubAddress register
 void setSubAddress #\( UInt8 #\) #\; UInt8 getSubAddress #\( #\) #\;;  Data register
 void setData #\( UInt8 #\) #\; UInt8 getData #\( #\) #\;;  handles the hardware interrupts for the i2c:
 static void handleHardwareInterrupt #\( OSObject * target #\, void * refCon #\, IOService * nub #\, int source #\) #\;;  methods to setup and abort a transfer:
;  (inheriting classes must call the parten method)
 virtual bool setAddressAndDirection #\( #\) #\; virtual bool abortTransfer #\( #\) #\;;  Waits for the completion of a read or write
;  operation:
 bool waitForCompletion #\( #\) #\;             ;  Each mode requires a specific interrupt handler (since the states are different for each mode)
;  so here it is the one for the Standard + SubAddress mode:
 bool i2cStandardSubModeInterrupts #\( UInt8 interruptStatus #\) #\;;  Initialize the address of the registers and the registers themselfs:
 virtual bool initI2CBus #\( UInt8 * baseAddress #\, UInt8 steps #\) #\;;  These instead set the speed:
 virtual bool setKhzSpeed #\( UInt #\) #\;      ;  The interrupt handler:
;  (inheriting classes must call the parent method)
 virtual bool handleI2CInterrupt #\( #\) #\; public #\:;  the standard inherits from IOService:
 virtual void free #\( #\) #\; virtual bool start #\( IOService * #\) #\;;  Starts the use of the interface:
 virtual bool openI2CBus #\( UInt8 port #\) #\; ;  These are to setup the mode for the I2C bus:
 virtual bool setPollingMode #\( bool #\) #\; virtual void setDumbMode #\( #\) #\; virtual void setStandardMode #\( #\) #\; virtual void setStandardSubMode #\( #\) #\; virtual void setCombinedMode #\( #\) #\;;  Test to read the values set by the funtions above:
 virtual bool isInDumbMode #\( #\) #\; virtual bool isInStandardMode #\( #\) #\; virtual bool isInStandardSubMode #\( #\) #\; virtual bool isInCombinedMode #\( #\) #\;;  These instead returns the speed:
 virtual UInt getKhzSpeed #\( #\) #\;           ;  Writes a block of data at a given address:
 virtual bool writeI2CBus #\( UInt8 address #\, UInt8 subAddress #\, UInt8 * data #\, UInt16 len #\) #\;;  Reads a block of data at a given address:
 virtual bool readI2CBus #\( UInt8 address #\, UInt8 subAddress #\, UInt8 * data #\, UInt16 len #\) #\;;  End using the interface:
 virtual bool closeI2CBus #\( #\) #\;           ;  Returns the name of the resource depending from
;  where the interface attaches:
;  the two most common names are:
;  PPCI2CInterface.i2c-uni-n for the i2c to uni-n
;  PPCI2CInterface.i2c-mac-io for the i2c to mac-io
;  but look in the OF device tree to find out the
;  extension of the i2c bus you are interested in.
 virtual const char * getResourceName #\( #\) #\;;  Overides the standard callPlatformFunction to catch all the calls
;  that may be directed to the PPCI2CInterface
 virtual IOReturn callPlatformFunction #\( const OSSymbol * functionName #\, bool waitForFunction #\, void * param1 #\, void * param2 #\, void * param3 #\, void * param4 #\) #\; virtual IOReturn callPlatformFunction #\( const char * functionName #\, bool waitForFunction #\, void * param1 #\, void * param2 #\, void * param3 #\, void * param4 #\) #\; virtual bool setI2cTimeout #\( UInt16 i2cTimeout #\) #\;
|#

; #endif //_PPCI2CINTERFACE_H


(provide-interface "PPCI2CInterface")